package com.paipai.mq;


import com.paipai.entity.Round;
import com.paipai.utils.JsonUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Configuration
public class RabbitConfig {
    //消息回调机制
    @Bean
    public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate();

        rabbitTemplate.setConnectionFactory(connectionFactory);

        //设置开启Mandatory,才能触发回调函数,无论消息推送结果怎么样都强制调用回调函数
        rabbitTemplate.setMandatory(true);

        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            //confirm 保证的是生产者到交换机过程
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                System.out.println("ConfirmCallback-correlationData:     " + "相关数据：" + correlationData);
                Message returnedMessage = correlationData.getReturnedMessage();
                Round round = JsonUtils.toObj(new String(returnedMessage.getBody()), Round.class);
                System.out.println("round:     " + JsonUtils.toJson(round));
                System.out.println("ConfirmCallback-ack:     " + "确认情况：" + ack);
                System.out.println("ConfirmCallback-cause:     " + "原因：" + cause);
                if (!ack) {
                    //如果ack为false 表示生产者发送到交换机过程失败，可能交换机不存在或者网络异常,导致没有发送到交换机
                    //重新发送 避免消息丢失
                    System.out.println("-----------------------------------------------重新发送消息---------------------------------------");
                    long expiration=round.getStarttime().getTime()-new Date().getTime();
                    //定义message对象
                    Message message= MessageBuilder.withBody(JsonUtils.toJson(round).getBytes()).setExpiration(String.valueOf(expiration)).build();
                    //发送消息
                    rabbitTemplate.convertAndSend("scheduledStartRoundExchange","roukey2",message,correlationData);
                    System.out.println("当前时间："+new Date().toString()+"编号："+round.getId()+"入队"+"过期时间："+expiration/(1000.0*60)+"分钟");
                }
            }
        });

        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                System.out.println("ReturnCallback:     " + "消息：" + message);
                System.out.println("ReturnCallback:     " + "回应码：" + replyCode);
                System.out.println("ReturnCallback:     " + "回应信息：" + replyText);
                System.out.println("ReturnCallback:     " + "交换机：" + exchange);
                System.out.println("ReturnCallback:     " + "路由键：" + routingKey);
                System.out.println("-----------------------------------------------重新发送消息---------------------------------------");
                Round round = JsonUtils.toObj(new String(message.getBody()), Round.class);
                long expiration=round.getStarttime().getTime()-new Date().getTime();
                //定义message对象
                Message newMessage= MessageBuilder.withBody(JsonUtils.toJson(round).getBytes()).setExpiration(String.valueOf(expiration)).build();
                //定义CorrelationData对象以及消息属性。不然comfirm方法无论失败还是成功，CorrelationData参数永远是null
                CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
                correlationData.setReturnedMessage(new Message(JsonUtils.toJson(round).getBytes(),new MessageProperties()));
                //发送消息
                rabbitTemplate.convertAndSend("scheduledStartRoundExchange","roukey2",newMessage,correlationData);
                System.out.println("当前时间："+new Date().toString()+"编号："+round.getId()+"入队"+"过期时间："+expiration/(1000.0*60)+"分钟");
            }
        });

        return rabbitTemplate;
    }

}
